package org.munoz.shared;

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// //////////////////////////////////////////////////////////////////////////////


import java.util.Arrays;
import java.util.Comparator;

/**
 * Representation of a single playing card. A card consists of a suit value (e.g. hearts, spades), a
 * rank value (e.g. ace, 7, king), and an image of the front of the card. A card object is
 * immutable; once instantiated, the values cannot change.
 * 
 * @author John K. Estell
 * @version 1.0
 */
public class Card extends Equality implements MatchMove {
  private static final long serialVersionUID = 1L;


  public static final Comparator<Card> NORMAL_COMPARATOR = new Comparator<Card>() {
    @Override
    public int compare(Card o1, Card o2) {
      int rankDiff = o1.getRank().compareTo(o2.getRank());
      return rankDiff == 0 ? o1.getSuit().compareTo(o2.getSuit()) : rankDiff;
    }
  };

  public static final Comparator<Card> SUIT_MAJOR_COMPARATOR = new Comparator<Card>() {
    @Override
    public int compare(Card o1, Card o2) {
      int suitDiff = o1.getSuit().compareTo(o2.getSuit());
      return suitDiff == 0 ? o1.getRank().compareTo(o2.getRank()) : suitDiff;
    }
  };

  public static final Comparator<Card> ACE_LOW_COMPARATOR = new Comparator<Card>() {
    @Override
    public int compare(Card o1, Card o2) {
      int rankDiff = Rank.ACE_LOW_COMPARATOR.compare(o1.getRank(), o2.getRank());
      return rankDiff == 0 ? o1.getSuit().compareTo(o2.getSuit()) : rankDiff;
    }
  };

  public static final Comparator<Card> TWO_HIGH_COMPARATOR = new Comparator<Card>() {
    @Override
    public int compare(Card o1, Card o2) {
      int rankDiff = Rank.TWO_HIGH_COMPARATOR.compare(o1.getRank(), o2.getRank());
      int suitDiff = Suit.TWO_HIGH_COMPARATOR.compare(o1.getSuit(), o2.getSuit());
      return rankDiff == 0 ? suitDiff : rankDiff;
    }
  };

  private Suit suitValue;
  private Rank rankValue;


  /**
   * Creates a new playing card.
   * 
   * @param suit the suit value of this card.
   * @param rank the rank value of this card.
   */
  public Card(Suit suit, Rank rank) {
    suitValue = suit;
    rankValue = rank;
  }

  /**
   * get a copy of this card.
   * */
  public Card getCopy() {
    return new Card(this.suitValue, this.rankValue);
  }

  /**
   * Returns the suit of the card.
   * 
   * @return a Suit constant representing the suit value of the card.
   */
  public Suit getSuit() {
    return suitValue;
  }


  /**
   * Returns the rank of the card.
   * 
   * @return a Rank constant representing the rank value of the card.
   */
  public Rank getRank() {
    return rankValue;
  }

  /**
   * Returns a description of this card.
   * 
   * @return the name of the card.
   */
  @Override
  public String toString() {
    return rankValue.toString() + " of " + suitValue.toString();
  }


  /**
   * Returns a description of the rank of this card.
   * 
   * @return the rank value of the card as a string.
   */
  public String rankToString() {
    return rankValue.toString();
  }


  /**
   * Returns a description of the suit of this card.
   * 
   * @return the suit value of the card as a string.
   */
  public String suitToString() {
    return suitValue.toString();
  }

  @Override
  public Object getId() {
    return Arrays.asList(suitValue, rankValue);
  }

}
